package com.learning.rpc.rpc.protocol.lrpc;

import com.learning.rpc.common.serialize.Serialization;
import com.learning.rpc.common.tool.SpiUtils;
import com.learning.rpc.common.tool.URIUtils;
import com.learning.rpc.remoting.Client;
import com.learning.rpc.remoting.Transporter;
import com.learning.rpc.rpc.Invocation;
import com.learning.rpc.rpc.Invoker;
import com.learning.rpc.rpc.Response;
import com.learning.rpc.rpc.protocol.ClientInvoker;
import com.learning.rpc.rpc.protocol.Protocol;
import com.learning.rpc.rpc.protocol.lrpc.codec.LrpcCodec;
import com.learning.rpc.rpc.protocol.lrpc.handler.LrpcClientHandler;
import com.learning.rpc.rpc.protocol.lrpc.handler.LrpcServerHandler;

import java.net.URI;

/**
 * ClassName: LRPCProtocol
 * Description: 协议实现类（完成协议的）
 * Date: 2022/5/16 17:22 【需求编号】
 *
 * @author Sam Sho
 * @version V1.0.0
 */
public class LrpcProtocol implements Protocol {

    @Override
    public void export(URI uri, Invoker invoker) {

        final String serializationName = URIUtils.getParam(uri, "serialization");
        final Serialization serialization = (Serialization) SpiUtils.getServiceImpl(serializationName, Serialization.class);

        // 1. 编解码器
        LrpcCodec lrpcCodec = new LrpcCodec();
        lrpcCodec.setDecodeType(Invocation.class);
        lrpcCodec.setSerialization(serialization);

        // 2. 收到请求处理器
        LrpcServerHandler lrpcServerHandler = new LrpcServerHandler();
        lrpcServerHandler.setInvoker(invoker);
        lrpcServerHandler.setSerialization(serialization);

        // 3. 底层网络框架
        final String transporterName = URIUtils.getParam(uri, "transporter");
        final Transporter transporter = (Transporter) SpiUtils.getServiceImpl(transporterName, Transporter.class);

        // 4. 启动服务
        transporter.start(uri, lrpcCodec, lrpcServerHandler);
    }

    @Override
    public Invoker refer(URI uri) {
        // 1. 找到序列化
        String serializationName = URIUtils.getParam(uri, "serialization");
        Serialization serialization = (Serialization) SpiUtils.getServiceImpl(serializationName, Serialization.class);
        // 2. 编解码器
        LrpcCodec codec = new LrpcCodec();
        // 客户端 -- 解码 -- 服务端发送过来的响应
        codec.setDecodeType(Response.class);
        codec.setSerialization(serialization);
        // 3. 收到响应 处理
        LrpcClientHandler lrpcClientHandler = new LrpcClientHandler();
        // 4. 连接 -- 长连接
        String transporterName = URIUtils.getParam(uri, "transporter");
        Transporter transporter = (Transporter) SpiUtils.getServiceImpl(transporterName, Transporter.class);
        Client connect = transporter.connect(uri, codec, lrpcClientHandler);

        // 5. 创建一个 invoker 通过网络连接发送数据
        return new ClientInvoker(connect, serialization);
    }
}
